package com.bingxue.edu.framework.security.justauth;

import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.StrUtil;
import com.bingxue.edu.framework.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.cache.AuthStateCache;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.config.AuthDefaultSource;
import me.zhyd.oauth.config.AuthSource;
import me.zhyd.oauth.request.AuthAlipayRequest;
import me.zhyd.oauth.request.AuthAliyunRequest;
import me.zhyd.oauth.request.AuthAmazonRequest;
import me.zhyd.oauth.request.AuthBaiduRequest;
import me.zhyd.oauth.request.AuthCodingRequest;
import me.zhyd.oauth.request.AuthDingTalkAccountRequest;
import me.zhyd.oauth.request.AuthDingTalkRequest;
import me.zhyd.oauth.request.AuthDouyinRequest;
import me.zhyd.oauth.request.AuthElemeRequest;
import me.zhyd.oauth.request.AuthFacebookRequest;
import me.zhyd.oauth.request.AuthFeishuRequest;
import me.zhyd.oauth.request.AuthGiteeRequest;
import me.zhyd.oauth.request.AuthGithubRequest;
import me.zhyd.oauth.request.AuthGitlabRequest;
import me.zhyd.oauth.request.AuthGoogleRequest;
import me.zhyd.oauth.request.AuthHuaweiRequest;
import me.zhyd.oauth.request.AuthJdRequest;
import me.zhyd.oauth.request.AuthKujialeRequest;
import me.zhyd.oauth.request.AuthLineRequest;
import me.zhyd.oauth.request.AuthLinkedinRequest;
import me.zhyd.oauth.request.AuthMeituanRequest;
import me.zhyd.oauth.request.AuthMiRequest;
import me.zhyd.oauth.request.AuthMicrosoftRequest;
import me.zhyd.oauth.request.AuthOktaRequest;
import me.zhyd.oauth.request.AuthOschinaRequest;
import me.zhyd.oauth.request.AuthPinterestRequest;
import me.zhyd.oauth.request.AuthQqRequest;
import me.zhyd.oauth.request.AuthRenrenRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.request.AuthSlackRequest;
import me.zhyd.oauth.request.AuthStackOverflowRequest;
import me.zhyd.oauth.request.AuthTaobaoRequest;
import me.zhyd.oauth.request.AuthTeambitionRequest;
import me.zhyd.oauth.request.AuthToutiaoRequest;
import me.zhyd.oauth.request.AuthTwitterRequest;
import me.zhyd.oauth.request.AuthWeChatEnterpriseQrcodeV2Request;
import me.zhyd.oauth.request.AuthWeChatEnterpriseWebRequest;
import me.zhyd.oauth.request.AuthWeChatMpRequest;
import me.zhyd.oauth.request.AuthWeChatOpenRequest;
import me.zhyd.oauth.request.AuthWeiboRequest;
import me.zhyd.oauth.request.AuthXmlyRequest;
import org.springframework.stereotype.Component;

/**
 * @author panbo
 * @since 2024/7/27
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AuthRequestFactory {

    private final JustAuthProperties properties;
    private final AuthStateCache authStateCache;

    /**
     * 返回AuthRequest对象
     *
     * @param source {@link AuthSource}
     * @return {@link AuthRequest}
     */
    public AuthRequest get(String source) {
        if (StrUtil.isBlank(source)) {
            throw new BusinessException("认证源不能为空");
        }
        AuthRequest authRequest = getDefaultRequest(source);
        if (authRequest == null) {
            throw new BusinessException(String.format("暂不支持 [%s] 平台账号登录", source));
        }
        return authRequest;
    }

    /**
     * 获取默认的 Request
     *
     * @param source {@link AuthSource}
     * @return {@link AuthRequest}
     */
    private AuthRequest getDefaultRequest(String source) {
        AuthDefaultSource authDefaultSource;

        try {
            authDefaultSource = EnumUtil.fromString(AuthDefaultSource.class, source.toUpperCase());
        } catch (IllegalArgumentException e) {
            // 无自定义匹配
            return null;
        }

        AuthConfig config = properties.getType().get(authDefaultSource.name());
        // 找不到对应关系，直接返回空
        if (config == null) {
            return null;
        }

        return switch (authDefaultSource) {
            case GITHUB -> new AuthGithubRequest(config, authStateCache);
            case WEIBO -> new AuthWeiboRequest(config, authStateCache);
            case GITEE -> new AuthGiteeRequest(config, authStateCache);
            case DINGTALK -> new AuthDingTalkRequest(config, authStateCache);
            case DINGTALK_ACCOUNT -> new AuthDingTalkAccountRequest(config, authStateCache);
            case BAIDU -> new AuthBaiduRequest(config, authStateCache);
            case CODING -> new AuthCodingRequest(config, authStateCache);
            case OSCHINA -> new AuthOschinaRequest(config, authStateCache);
            case ALIPAY -> new AuthAlipayRequest(config, authStateCache);
            case QQ -> new AuthQqRequest(config, authStateCache);
            case WECHAT_OPEN -> new AuthWeChatOpenRequest(config, authStateCache);
            case WECHAT_MP -> new AuthWeChatMpRequest(config, authStateCache);
            case WECHAT_ENTERPRISE -> new AuthWeChatEnterpriseQrcodeV2Request(config, authStateCache);
            case WECHAT_ENTERPRISE_WEB -> new AuthWeChatEnterpriseWebRequest(config, authStateCache);
            case TAOBAO -> new AuthTaobaoRequest(config, authStateCache);
            case GOOGLE -> new AuthGoogleRequest(config, authStateCache);
            case FACEBOOK -> new AuthFacebookRequest(config, authStateCache);
            case DOUYIN -> new AuthDouyinRequest(config, authStateCache);
            case LINKEDIN -> new AuthLinkedinRequest(config, authStateCache);
            case MICROSOFT -> new AuthMicrosoftRequest(config, authStateCache);
            case MI -> new AuthMiRequest(config, authStateCache);
            case TOUTIAO -> new AuthToutiaoRequest(config, authStateCache);
            case TEAMBITION -> new AuthTeambitionRequest(config, authStateCache);
            case RENREN -> new AuthRenrenRequest(config, authStateCache);
            case PINTEREST -> new AuthPinterestRequest(config, authStateCache);
            case STACK_OVERFLOW -> new AuthStackOverflowRequest(config, authStateCache);
            case HUAWEI -> new AuthHuaweiRequest(config, authStateCache);
            case GITLAB -> new AuthGitlabRequest(config, authStateCache);
            case KUJIALE -> new AuthKujialeRequest(config, authStateCache);
            case ELEME -> new AuthElemeRequest(config, authStateCache);
            case MEITUAN -> new AuthMeituanRequest(config, authStateCache);
            case TWITTER -> new AuthTwitterRequest(config, authStateCache);
            case FEISHU -> new AuthFeishuRequest(config, authStateCache);
            case JD -> new AuthJdRequest(config, authStateCache);
            case ALIYUN -> new AuthAliyunRequest(config, authStateCache);
            case XMLY -> new AuthXmlyRequest(config, authStateCache);
            case AMAZON -> new AuthAmazonRequest(config, authStateCache);
            case SLACK -> new AuthSlackRequest(config, authStateCache);
            case LINE -> new AuthLineRequest(config, authStateCache);
            case OKTA -> new AuthOktaRequest(config, authStateCache);
            default -> null;
        };
    }

}
